package corerun

import (
	"core/action"
	"core/coreentity"
	"core/coreservice"
	"core/corestruct"
	"core/coreutil"
	"core/datetime"
	"core/id"
	"core/myerrors"
	"fmt"
	"gorm.io/gorm"
	"strings"
	"time"
)

type actiondb struct {
	ctx     *corestruct.HttpContext
	Ldb     *[]coreentity.HtAction
	DB      *gorm.DB
	PrjName string
	Lcls    *[]coreentity.HtCls
}

/**
*刷新Action到数据库
 */
func (p *actiondb) RefreshToDb() error {

	var ldb = make([]coreentity.HtAction, 0)
	p.Ldb = &ldb

	tx := p.DB.
		Model(&coreentity.HtAction{}).
		Unscoped().
		Where("prj_name=?", p.PrjName).
		Find(p.Ldb)
	if tx.Error != nil {
		return myerrors.NewByErr(tx.Error)
	}

	for _, mcls := range coreutil.ActionUtil.GetAllAction() {
		if mcls.PrjName != p.PrjName {
			continue
		}
		p.RefreshToDbAction(&mcls)
	}

	if tx.Error != nil {
		return tx.Error
	}

	//根据类型判断更新日期
	tx = p.DB.
		Model(&coreentity.HtCls{}).
		Select("id,full_name,edt_dt")

	var svrcls = &coreservice.ListService[coreentity.HtCls]{}
	var err error
	p.Lcls, err = svrcls.List(p.ctx, tx)
	if err != nil {
		return err
	}

	tx = p.DB.
		Model(&coreentity.HtAction{})
	var svract = &coreservice.ListService[coreentity.HtAction]{}
	p.Ldb, err = svract.List(p.ctx, tx)
	if err != nil {
		return err
	}

	for _, mact := range *p.Ldb {
		var memo = ""
		if mact.PinType != "" {
			var mdbcls = p.FindCls(mact.PinType)
			if mdbcls != nil && time.Time(mact.EdtDt).UnixNano() < time.Time(mdbcls.EdtDt).UnixNano() {
				memo += "参数 " + mact.PinType + "更新 "
			}
		}

		if mact.PoutType != "" {
			var mdbcls = p.FindCls(mact.PoutType)
			if mdbcls != nil && time.Time(mact.EdtDt).UnixNano() < time.Time(mdbcls.EdtDt).UnixNano() {
				memo += "返回结构 " + mact.PoutType + "更新 "
			}
		}
		if memo != "" {
			err = p.DB.Transaction(func(tx2 *gorm.DB) error {
				tx3 := tx2.Updates(coreentity.HtAction{Id: mact.Id, EdtDt: datetime.Now()})
				if tx3.Error != nil {
					return tx3.Error
				}
				var mcode = p.CreateHTCodeLogByDto(&mact)
				mcode.Memo = memo
				tx3 = tx2.Create(mcode)
				if tx3.Error != nil {
					return tx3.Error
				}
				return nil
			})

			if err != nil {
				return err
			}
		}
	}

	return nil
}
func (p actiondb) FindCls(fullName string) *coreentity.HtCls {
	for _, v := range *p.Lcls {
		if v.FullName == fullName {
			return &v
		}
	}
	return nil
}

func (p actiondb) FindFromDb(fullUrl string) *coreentity.HtAction {
	for _, v := range *p.Ldb {
		if v.FullUrl == fullUrl {
			return &v
		}
	}
	return nil
}
func (p *actiondb) GetType(s string) string {
	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}
	if strings.HasPrefix(s, "[]") {
		s = s[2:]
	}
	if strings.HasPrefix(s, "corestruct.Page[") {
		s = s[16:]
		s = strings.Trim(s, "]")
		var arr = strings.Split(s, "/")
		s = arr[len(arr)-1]
	}

	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}

	return s
}
func (p *actiondb) CopyPinType(mcls *action.Action, mact *coreentity.HtAction) {
	var s = mcls.PinType
	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}
	if strings.HasPrefix(s, "[]") {
		s = s[2:]
		mact.PinIslist = true
	}
	if strings.HasPrefix(s, "corestruct.Page[") {
		s = s[16:]
		s = strings.Trim(s, "]")
		var arr = strings.Split(s, "/")
		s = arr[len(arr)-1]
	}

	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}
	mact.PinType = s
}

func (p *actiondb) CopyPoutType(mcls *action.Action, mact *coreentity.HtAction) {
	var s = mcls.PoutType
	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}
	if strings.HasPrefix(s, "[]") {
		s = s[2:]
		mact.PoutIslist = true
	}
	if strings.HasPrefix(s, "corestruct.Page[") {
		s = s[16:]
		s = strings.Trim(s, "]")
		var arr = strings.Split(s, "/")
		s = arr[len(arr)-1]
		mact.PoutIspage = true
	}

	if strings.HasPrefix(s, "*") {
		s = s[1:]
	}
	mact.PoutType = s
}
func (p *actiondb) getDbAction(mcls *action.Action) *coreentity.HtAction {
	var mdb = &coreentity.HtAction{
		Id:          0,
		PrjName:     p.PrjName,
		CtlFullName: "",
		FullUrl:     mcls.FullUrl,
		Name:        mcls.Name,
		Ename:       mcls.Ename,
		Memo:        mcls.Memo,
		PinType:     mcls.PinType,
		PinIslist:   mcls.PinIslist,
		PoutType:    mcls.PoutType,
		PoutIslist:  mcls.PoutIslist,
		PoutIspage:  mcls.PoutIspage,
		AuthType:    mcls.AuthType,
		LogNeed:     mcls.LogNeed,
		LogTemplete: mcls.LogTemplete,
		LogPin:      mcls.LogPin,
		LogPout:     mcls.LogPout,
		CrtDt:       datetime.MyTime{},
		EdtDt:       datetime.MyTime{},
		Deleted:     0,
	}
	p.CopyPinType(mcls, mdb)
	p.CopyPoutType(mcls, mdb)
	return mdb
}
func (p *actiondb) RefreshToDbAction(mcls *action.Action) error {
	var mdb = p.FindFromDb(mcls.FullUrl)
	if mdb == nil {
		mdb = p.getDbAction(mcls)
		mdb.Id = id.Idutil.GetId()
		tx := coreservice.BaseService.Insert(mdb, p.DB)
		if tx.Error != nil {
			return tx.Error
		}
		var mcodelog = p.CreateHTCodeLogByDto(mdb)
		mcodelog.Memo = "新增"
		tx = coreservice.BaseService.Insert(mcodelog, p.DB)
		if tx.Error != nil {
			return tx.Error
		}
	} else {
		var mdb2 = p.getDbAction(mcls)
		mdb2.Id = mdb.Id
		mdb2.CrtDt = mdb.CrtDt

		var msg = p.CompareCls(mdb2, mdb)
		if mdb.Deleted > 0 {
			mdb.Deleted = datetime.DeletedAt(0)
			msg = "删除恢复\r\n" + msg
		}
		if "" != msg {

			tx := p.DB.Unscoped()
			tx = coreservice.BaseService.UpdateByDto(mdb2, &coreentity.HtAction{
				Id: mdb.Id,
			},
				tx)
			if tx.Error != nil {
				return nil
			}
			var mcodelog = p.CreateHTCodeLogByDto(mdb)
			mcodelog.Memo = msg
			tx = coreservice.BaseService.Insert(mcodelog, p.DB)
			if tx.Error != nil {
				return tx.Error
			}
		}
	}
	return nil
}
func (p actiondb) CreateHTCodeLogByDto(mdb *coreentity.HtAction) *coreentity.HtCodeLog {
	var mcodelog = &coreentity.HtCodeLog{

		Id:       coreutil.IdUtil.GetId(),
		PrjName:  mdb.PrjName,
		Bid:      mdb.Id,
		Lx:       "action",
		FullName: mdb.FullUrl,
		Name:     mdb.Name,
		Memo:     "",
		CrtDt:    datetime.MyTime(time.Now()),
	}
	return mcodelog
}

/**
*比较类型 数据库差异
 */
func (p actiondb) CompareCls(mcls *coreentity.HtAction, mdb *coreentity.HtAction) string {

	var sf = ""

	sf += p.CompareClsField(mcls, mdb, "FullUrl")
	sf += p.CompareClsField(mcls, mdb, "Name")
	sf += p.CompareClsField(mcls, mdb, "Ename")
	sf += p.CompareClsField(mcls, mdb, "Memo")
	sf += p.CompareClsField(mcls, mdb, "PinType")
	sf += p.CompareClsField(mcls, mdb, "PinIslist")
	sf += p.CompareClsField(mcls, mdb, "PoutType")
	sf += p.CompareClsField(mcls, mdb, "PoutIslist")
	sf += p.CompareClsField(mcls, mdb, "PoutIspage")
	sf += p.CompareClsField(mcls, mdb, "AuthType")

	return sf
}

/**
*比较字段
 */
func (p actiondb) CompareClsField(mf *coreentity.HtAction, mdb *coreentity.HtAction, fieldName string) string {
	var v = fmt.Sprintf("%v", coreutil.StructUtil.GetFieldValue(mf, fieldName))
	var dbv = fmt.Sprintf("%v", coreutil.StructUtil.GetFieldValue(mdb, fieldName))
	if v != dbv && v != "*"+dbv {
		return fieldName + " " + dbv + "=>" + v
	}
	return ""
}
